// /////////////////////////////////////////////////////////////////////////////
//
// Name:            LightComponent.cpp
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           Component wrapper of Irrlicht's ILightSceneNode.
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

// Include files
#include "LightComponent.h"
#include "../../core/GameManager.h"


// LightComponent class
// LightComponent constructor. (default)
LightComponent::LightComponent(Entity *parent, const SColorf &color, f32 radius)
: SceneComponent(parent, true)
{
    if(pParent != NULL)
    {
       // Get pointers to needed sub-systems of the Game Manager.
       ISceneManager *pSceneMgr = GameManager::Instance()->getSceneManager();

       // Create the internal scene node.
       mLightSN = pSceneMgr->addLightSceneNode(0, parent->getAbsolutePosition(), color, radius,
                                               parent->getID());
       mSceneNode = mLightSN;

       // Set-up internal mechanism for collision detection.
       mTriSelector = NULL;
       mMetaSelector = NULL;
    }
}

// LightComponent deconstructor.
LightComponent::~LightComponent()
{
    if(pParent != NULL)
    {
       mLightSN->remove();
       mSceneNode = NULL;
    }
}

// Returns a direct pointer to the ILightSceneNode.
ILightSceneNode* LightComponent::getLightSceneNode()
{
    return mLightSN;
}

// Returns whether this light casts shadows.
bool LightComponent::getCastShadow() const
{
    return mLightSN->getCastShadow();
}

// Gets the light type.
E_LIGHT_TYPE LightComponent::getLightType() const
{
    return mLightSN->getLightType();
}

// Gets the light's radius of influence.
f32 LightComponent::getRadius() const
{
    return mLightSN->getRadius();
}

// Sets whether this light casts shadows.
void LightComponent::setCastShadow(bool shadow)
{
    mLightSN->enableCastShadow(shadow);
}

// Sets the light type.
void LightComponent::setLightType(E_LIGHT_TYPE type)
{
    mLightSN->setLightType(type);
}

// Sets the light's radius of influence.
void LightComponent::setRadius(f32 radius)
{
    mLightSN->setRadius(radius);
}

// Serializes this object.
bool LightComponent::onSerialization(SerializedAttributes *attributes)
{
    // Create a root.
    SerializedAttributes *root = new SerializedAttributes();

    // Serialize attributes inherited from SceneComponent.
    SceneComponent::onSerialization(root);

    // Serialize attributes.
    root->pushBool("castShadow", getCastShadow());

         if(getLightType() == ELT_POINT)          root->pushString("lightType", "ELT_POINT");
    else if(getLightType() == ELT_SPOT)           root->pushString("lightType", "ELT_SPOT");
    else if(getLightType() == ELT_DIRECTIONAL)    root->pushString("lightType", "ELT_DIRECTIONAL");

    root->pushFloat("radius", getRadius());

    // Add root to the given collection of attributes.
    attributes->pushObject("LightComponent", root);
    root->drop();

    // Return
    return true;
}

// Deserializes this object.
bool LightComponent::onDeserialization(SerializedAttributes *attributes)
{
    // Retrieve root attribute from the collection.
    SerializedAttribute *rootAttribute = attributes->pullAttribute();

    if(rootAttribute == NULL || rootAttribute->getName() != "LightComponent")
      return false;

    SerializedAttributes *root = reinterpret_cast<SerializedAttributes*>(rootAttribute->getObject());
    root->grab();

    rootAttribute->drop(); // We no longer need this attribute.

    // Process all attributes in the root collection.
    for(SerializedAttribute *attribute = root->pullAttribute(); attribute != NULL; attribute = root->pullAttribute())
    {
       // Deserialize attributes.
       if(attribute->getName() == "SceneComponent")
       {
           // Rewrap attribute so that it can be deserialized properly.
           SerializedAttributes *wrappedAttribute = new SerializedAttributes();
           wrappedAttribute->pushAttribute(attribute);

           // Deserialize the component.
           SceneComponent::onDeserialization(wrappedAttribute);

           // Clean up.
           wrappedAttribute->drop();
       }

       else if(attribute->getName() == "castShadow")   setCastShadow(attribute->getBool());

       else if(attribute->getName() == "lightType")
       {
                if(attribute->getString() == "ELT_POINT")          setLightType(ELT_POINT);
           else if(attribute->getString() == "ELT_SPOT")           setLightType(ELT_SPOT);
           else if(attribute->getString() == "ELT_DIRECTIONAL")    setLightType(ELT_DIRECTIONAL);
       }

       else if(attribute->getName() == "radius")   setRadius(attribute->getFloat());

       // We no longer need a reference to the attribute.
       attribute->drop();
    }

    // We no longer need a reference to the root.
    root->drop();

    // We're done.
    return true;
}

// End of File
